package com.diy.sigmund.diycommon.util.thread;

/**
 * @author ylm-sigmund
 * @since 2023/3/4 20:25
 */
public class ThreadWaitNotifyDemo {

    /**
     * ThreadWait start Thread-0
     * ThreadWait start Thread-1
     * ThreadNotify start Thread-2
     * ThreadNotify end Thread-2
     * ThreadWait end Thread-1
     * ThreadWait end Thread-0
     */
    public static void main(String[] args) throws InterruptedException {
        final Object lock = new Object();
        final ThreadWait threadWait = new ThreadWait(lock);
        threadWait.start();
        final ThreadWait threadWait1 = new ThreadWait(lock);
        threadWait1.start();

        // 保证等待线程先启动
        Thread.sleep(100);

        // 2个等待线程会一直阻塞
        // threadWait.join();
        // threadWait1.join();

        final ThreadNotify threadNotify = new ThreadNotify(lock);
        threadNotify.start();
    }

    static class ThreadWait extends Thread {

        private final Object lock;

        public ThreadWait(Object lock) {
            this.lock = lock;
        }

        @Override
        public void run() {
            synchronized (lock) {
                System.out.println("ThreadWait start " + Thread.currentThread().getName());
                try {
                    // 实现线程的阻塞
                    lock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("ThreadWait end " + Thread.currentThread().getName());
            }
        }
    }

    static class ThreadNotify extends Thread {

        private final Object lock;

        public ThreadNotify(Object lock) {
            this.lock = lock;
        }

        @Override
        public void run() {
            synchronized (lock) {
                System.out.println("ThreadNotify start " + Thread.currentThread().getName());
                // 唤醒被阻塞的线程,若有多个线程阻塞，则只会有一个线程竞争到锁，只有一个线程会从等待队列waitSet转移到同步队列entryList
                lock.notify();
                // 唤醒被阻塞的线程,若有多个线程阻塞，则都能竞争到锁
                // lock.notifyAll();
                System.out.println("ThreadNotify end " + Thread.currentThread().getName());
            }
        }

    }
}
